package xeroxware.framework.mybatis;

import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Intercepts({ @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class ResultSetAspect implements Interceptor {

	private static final Logger logger = LoggerFactory.getLogger(ResultSetAspect.class);

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Statement statement = (Statement) invocation.getArgs()[0];
		ResultSetMetaData rsmd = statement.getResultSet().getMetaData();

		List<ColumnMetaData> list = new ArrayList<ColumnMetaData>();

		for (int i = 1; i < rsmd.getColumnCount(); i++) {
			ColumnMetaData columnMetaData = new ColumnMetaData();

			columnMetaData.setCatalogName(rsmd.getCatalogName(i));
			columnMetaData.setColumnClassName(rsmd.getColumnClassName(i));
			columnMetaData.setColumnDisplaySize(rsmd.getColumnDisplaySize(i));
			columnMetaData.setColumnLabel(rsmd.getColumnLabel(i));
			columnMetaData.setColumnName(rsmd.getColumnName(i));
			columnMetaData.setColumnType(rsmd.getColumnType(i));
			columnMetaData.setPrecision(rsmd.getPrecision(i));
			columnMetaData.setScale(rsmd.getScale(i));
			columnMetaData.setSchemaName(rsmd.getSchemaName(i));
			columnMetaData.setTableName(rsmd.getTableName(i));
			columnMetaData.setAutoIncrement(rsmd.isAutoIncrement(i));
			columnMetaData.setCaseSensitive(rsmd.isCaseSensitive(i));
			columnMetaData.setCurrency(rsmd.isCurrency(i));
			columnMetaData.setDefinitelyWritable(rsmd.isDefinitelyWritable(i));
			columnMetaData.setNullable(rsmd.isNullable(i));
			columnMetaData.setReadOnly(rsmd.isReadOnly(i));
			columnMetaData.setSearchAble(rsmd.isSearchable(i));
			columnMetaData.setSigned(rsmd.isSigned(i));
			columnMetaData.setWritable(rsmd.isWritable(i));

			list.add(columnMetaData);
		}

		MetaDataHolder.setColumnMetaData(list);

		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		logger.info("===== MyBatis Property =====");

		Set<String> propertySet = properties.stringPropertyNames();
		Iterator<String> it = propertySet.iterator();
		String key;

		while (it.hasNext()) {
			key = it.next();

			logger.info("[{}] : {}", key, properties.get(key));
		}
	}
}
